home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / dev / c / ctags.lha / ctags-3.0.3 / fortran.c < prev    next >
C/C++ Source or Header  |  1999-02-17  |  23KB  |  983 lines

  1. /*****************************************************************************
  2. *   $Id: fortran.c,v 7.4 1998/12/22 03:28:47 darren Exp $
  3. *
  4. *   Copyright (c) 1998, Darren Hiebert
  5. *
  6. *   This source code is released for free distribution under the terms of the
  7. *   GNU General Public License.
  8. *
  9. *   This module contains functions for generating tags for Fortran language
  10. *   files.
  11. *****************************************************************************/
  12.  
  13. /*============================================================================
  14. =   Include files
  15. ============================================================================*/
  16. #include "general.h"
  17.  
  18. #include <string.h>
  19. #include <limits.h>
  20. #include <ctype.h>    /* to define tolower() */
  21. #include <setjmp.h>
  22.  
  23. #include "debug.h"
  24. #include "entry.h"
  25. #include "keyword.h"
  26. #include "main.h"
  27. #include "options.h"
  28. #include "parse.h"
  29. #include "read.h"
  30. #include "vstring.h"
  31.  
  32. /*============================================================================
  33. =   Macros
  34. ============================================================================*/
  35. #define isType(token,t)        (boolean)((token)->type == (t))
  36. #define isKeyword(token,k)    (boolean)((token)->keyword == (k))
  37.  
  38. /*============================================================================
  39. =   Data declarations
  40. ============================================================================*/
  41.  
  42. typedef enum eException {
  43.     ExceptionNone, ExceptionEOF, ExceptionFixedFormat
  44. } exception_t;
  45.  
  46. /*  Used to designate type of line read in fixed source form.
  47.  */
  48. typedef enum eFortranLineType {
  49.     LTYPE_UNDETERMINED,
  50.     LTYPE_INVALID,
  51.     LTYPE_COMMENT,
  52.     LTYPE_CONTINUATION,
  53.     LTYPE_EOF,
  54.     LTYPE_INITIAL,
  55.     LTYPE_SHORT
  56. } lineType;
  57.  
  58. /*  Used to specify type of keyword.
  59.  */
  60. typedef enum eKeywordId {
  61.     KEYWORD_NONE,
  62.     KEYWORD_assignment,
  63.     KEYWORD_block,
  64.     KEYWORD_common,
  65.     KEYWORD_data,
  66.     KEYWORD_end,
  67.     KEYWORD_entry,
  68.     KEYWORD_function,
  69.     KEYWORD_interface,
  70.     KEYWORD_module,
  71.     KEYWORD_namelist,
  72.     KEYWORD_operator,
  73.     KEYWORD_program,
  74.     KEYWORD_subroutine,
  75.     KEYWORD_type
  76. } keywordId;
  77.  
  78. /*  Used to determine whether keyword is valid for the token language and
  79.  *  what its ID is.
  80.  */
  81. typedef struct sKeywordDesc {
  82.     const char *name;
  83.     keywordId id;
  84. } keywordDesc;
  85.  
  86. typedef enum eTokenType {
  87.     TOKEN_UNDEFINED,
  88.     TOKEN_COMMA,
  89.     TOKEN_DECLARATION,
  90.     TOKEN_IDENTIFIER,
  91.     TOKEN_KEYWORD,
  92.     TOKEN_LABEL,
  93.     TOKEN_NEWLINE,
  94.     TOKEN_NUMERIC,
  95.     TOKEN_OPERATOR,
  96.     TOKEN_PAREN_CLOSE,
  97.     TOKEN_PAREN_OPEN,
  98.     TOKEN_STRING
  99. } tokenType;
  100.  
  101. typedef enum eTagType {
  102.     TAG_UNDEFINED,
  103.     TAG_BLOCK_DATA,
  104.     TAG_COMMON_BLOCK,
  105.     TAG_ENTRY_POINT,
  106.     TAG_FUNCTION,
  107.     TAG_INTERFACE,
  108.     TAG_LABEL,
  109.     TAG_MODULE,
  110.     TAG_NAMELIST,
  111.     TAG_PROGRAM,
  112.     TAG_SUBROUTINE,
  113.     TAG_DERIVED_TYPE,
  114.     TAG_VARIABLE,
  115.     TAG_COUNT        /* must be last */
  116. } tagType;
  117.  
  118. typedef struct sTokenInfo {
  119.     tokenType        type;
  120.     keywordId        keyword;
  121.     tagType        tag;
  122.     vString *        string;
  123.     unsigned long    lineNumber;
  124.     fpos_t        filePosition;
  125. } tokenInfo;
  126.  
  127. /*============================================================================
  128. =   Data definitions
  129. ============================================================================*/
  130.  
  131. static jmp_buf Exception;
  132. static int Ungetc = '\0';
  133. static unsigned int Column = 0;
  134. static boolean FreeSourceForm = FALSE;
  135. static tokenInfo *Parent = NULL;
  136.  
  137. static const keywordDesc FortranKeywordTable[] = {
  138.     /* keyword        keyword ID */
  139.     { "assignment",    KEYWORD_assignment    },
  140.     { "block",        KEYWORD_block        },
  141.     { "common",        KEYWORD_common        },
  142.     { "data",        KEYWORD_data        },
  143.     { "end",        KEYWORD_end        },
  144.     { "entry",        KEYWORD_entry        },
  145.     { "function",    KEYWORD_function    },
  146.     { "interface",    KEYWORD_interface    },
  147.     { "module",        KEYWORD_module        },
  148.     { "namelist",    KEYWORD_namelist    },
  149.     { "operator",    KEYWORD_operator    },
  150.     { "program",    KEYWORD_program        },
  151.     { "subroutine",    KEYWORD_subroutine    },
  152.     { "type",        KEYWORD_type        }
  153. };
  154.  
  155. /*============================================================================
  156. =   Function prototypes
  157. ============================================================================*/
  158. static void buildFortranKeywordHash __ARGS((void));
  159. static const char *tagName __ARGS((const tagType type));
  160. static int tagLetter __ARGS((const tagType type));
  161. static boolean includeTag __ARGS((const tagType type));
  162. static void copyToken __ARGS((tokenInfo *const dest, const tokenInfo *const src));
  163. static void makeFortranTag __ARGS((const tokenInfo *const token));
  164. static int skipLine __ARGS((void));
  165. static void makeLabelTag __ARGS((vString *const label));
  166. static lineType getLineType __ARGS((void));
  167. static int getFixedFormChar __ARGS((void));
  168. static int getFreeFormChar __ARGS((void));
  169. static int getChar __ARGS((void));
  170. static void ungetChar __ARGS((const int c));
  171. static vString *parseInteger __ARGS((int c));
  172. static vString *parseNumeric __ARGS((int c));
  173. static void parseString __ARGS((vString *const string, const int delimeter));
  174. static void parseIdentifier __ARGS((vString *const string, const int firstChar));
  175. static keywordId analyzeToken __ARGS((vString *const name));
  176. static int skipToChar __ARGS((const int toChar));
  177. static void readToken __ARGS((tokenInfo *const token));
  178. static void setTagType __ARGS((tokenInfo *const token, const tagType type));
  179. static void nameTag __ARGS((tokenInfo *const token, const tagType type));
  180. static void parseParenName __ARGS((tokenInfo *const token));
  181. static void parseInterface __ARGS((tokenInfo *const token));
  182. static void tagSlashName __ARGS((tokenInfo *const token, const tagType type));
  183. static void parseType __ARGS((tokenInfo *const token));
  184. static void parseBlock __ARGS((tokenInfo *const token));
  185. static void parseFile __ARGS((tokenInfo *const token));
  186. static tokenInfo *newToken __ARGS((void));
  187. static void deleteToken __ARGS((tokenInfo *const token));
  188. static void init __ARGS((void));
  189.  
  190. /*============================================================================
  191. =   Function definitions
  192. ============================================================================*/
  193.  
  194. static void buildFortranKeywordHash()
  195. {
  196.     const size_t count = sizeof(FortranKeywordTable) /
  197.              sizeof(FortranKeywordTable[0]);
  198.     size_t i;
  199.  
  200.     for (i = 0  ;  i < count  ;  ++i)
  201.     {
  202.     const keywordDesc *p = &FortranKeywordTable[i];
  203.  
  204.     addKeyword(p->name, LANG_FORTRAN, (int)p->id);
  205.     }
  206. }
  207.  
  208. /*----------------------------------------------------------------------------
  209. *-    Tag generation functions
  210. ----------------------------------------------------------------------------*/
  211.  
  212. static const char *tagName( type )
  213.     const tagType type;
  214. {
  215.     /*  Note that the strings in this array must correspond to the types in
  216.      *  the tagType enumeration.
  217.      */
  218.     static const char *names[] = {
  219.     "undefined", "block data", "common", "entry", "function",
  220.     "interface", "label", "module", "namelist", "program", "subroutine",
  221.     "type", "variable"
  222.     };
  223.  
  224.     Assert(sizeof(names)/sizeof(names[0]) == TAG_COUNT);
  225.  
  226.     return names[(int)type];
  227. }
  228.  
  229. static int tagLetter( type )
  230.     const tagType type;
  231. {
  232.     /*  Note that the characters in this list must correspond to the types in
  233.      *  the tagType enumeration.
  234.      */
  235.     const char *const chars = "?bcefilmnpstv";
  236.  
  237.     Assert(strlen(chars) == TAG_COUNT);
  238.  
  239.     return chars[(int)type];
  240. }
  241.  
  242. static boolean includeTag( type )
  243.     const tagType type;
  244. {
  245.     const struct sFortranInclude *const inc = &Option.include.fortran;
  246.     boolean include;
  247.  
  248.     switch (type)
  249.     {
  250.     case TAG_BLOCK_DATA:    include = inc->blockData;    break;
  251.     case TAG_COMMON_BLOCK:    include = inc->commonBlocks;    break;
  252.     case TAG_ENTRY_POINT:    include = inc->entryPoints;    break;
  253.     case TAG_FUNCTION:    include = inc->functions;    break;
  254.     case TAG_INTERFACE:    include = inc->interfaces;    break;
  255.     case TAG_MODULE:    include = inc->modules;        break;
  256.     case TAG_NAMELIST:    include = inc->namelists;    break;
  257.     case TAG_PROGRAM:    include = inc->programs;    break;
  258.     case TAG_SUBROUTINE:    include = inc->subroutines;    break;
  259.     case TAG_DERIVED_TYPE:    include = inc->types;        break;
  260.  
  261.     case TAG_LABEL:        include = (boolean)(inc->labels  &&
  262.                        Option.include.fileScope); break;
  263.  
  264.     default: